"""
位运算符
学习目标：
1. 理解二进制和位运算的概念
2. 掌握位运算符的使用
3. 了解位运算的实际应用场景
"""

# ==================== 1. 二进制基础 ====================
print("=" * 50)
print("1. 二进制基础知识")
print("=" * 50)

# 十进制转二进制
num = 10
print(f"十进制 {num} 的二进制表示：{bin(num)}")

num = 15
print(f"十进制 {num} 的二进制表示：{bin(num)}")

# 二进制转十进制
binary = 0b1010  # 0b表示二进制
print(f"二进制 0b1010 的十进制值：{binary}")

binary = 0b1111
print(f"二进制 0b1111 的十进制值：{binary}")

print("\n💡 Python中用 0b 前缀表示二进制数")
print("💡 bin() 函数可以将十进制转为二进制字符串")

print()

# ==================== 2. 按位与 & ====================
print("=" * 50)
print("2. 按位与 & (AND)")
print("=" * 50)

a = 12  # 二进制: 1100
b = 10  # 二进制: 1010
result = a & b  # 二进制: 1000 = 8

print(f"a = {a:4d}  (二进制: {bin(a)})")
print(f"b = {b:4d}  (二进制: {bin(b)})")
print(f"a & b = {result:2d}  (二进制: {bin(result)})")
print()
print("规则：两个位都是1，结果才是1")
print("  1100")
print("& 1010")
print("------")
print("  1000")

print()

# ==================== 3. 按位或 | ====================
print("=" * 50)
print("3. 按位或 | (OR)")
print("=" * 50)

a = 12  # 二进制: 1100
b = 10  # 二进制: 1010
result = a | b  # 二进制: 1110 = 14

print(f"a = {a:4d}  (二进制: {bin(a)})")
print(f"b = {b:4d}  (二进制: {bin(b)})")
print(f"a | b = {result:2d}  (二进制: {bin(result)})")
print()
print("规则：两个位只要有一个是1，结果就是1")
print("  1100")
print("| 1010")
print("------")
print("  1110")

print()

# ==================== 4. 按位异或 ^ ====================
print("=" * 50)
print("4. 按位异或 ^ (XOR)")
print("=" * 50)

a = 12  # 二进制: 1100
b = 10  # 二进制: 1010
result = a ^ b  # 二进制: 0110 = 6

print(f"a = {a:4d}  (二进制: {bin(a)})")
print(f"b = {b:4d}  (二进制: {bin(b)})")
print(f"a ^ b = {result:2d}  (二进制: {bin(result)})")
print()
print("规则：两个位不同时结果为1，相同时结果为0")
print("  1100")
print("^ 1010")
print("------")
print("  0110")

print()

# ==================== 5. 按位取反 ~ ====================
print("=" * 50)
print("5. 按位取反 ~ (NOT)")
print("=" * 50)

a = 5  # 二进制: 0000 0101
result = ~a  # 二进制: 1111 1010 (补码) = -6

print(f"a = {a}")
print(f"~a = {result}")
print()
print("规则：0变1，1变0")
print("💡 Python中使用补码表示，所以 ~n = -(n+1)")

print()

# ==================== 6. 左移 << ====================
print("=" * 50)
print("6. 左移 << ")
print("=" * 50)

a = 5  # 二进制: 101
print(f"a = {a}  (二进制: {bin(a)})")

result = a << 1  # 左移1位: 1010 = 10
print(f"a << 1 = {result}  (二进制: {bin(result)})")

result = a << 2  # 左移2位: 10100 = 20
print(f"a << 2 = {result}  (二进制: {bin(result)})")

result = a << 3  # 左移3位: 101000 = 40
print(f"a << 3 = {result}  (二进制: {bin(result)})")

print()
print("规则：向左移动n位，右边补0")
print("效果：相当于乘以 2^n")
print("💡 5 << 1 = 5 * 2 = 10")
print("💡 5 << 2 = 5 * 4 = 20")

print()

# ==================== 7. 右移 >> ====================
print("=" * 50)
print("7. 右移 >>")
print("=" * 50)

a = 20  # 二进制: 10100
print(f"a = {a}  (二进制: {bin(a)})")

result = a >> 1  # 右移1位: 1010 = 10
print(f"a >> 1 = {result}  (二进制: {bin(result)})")

result = a >> 2  # 右移2位: 101 = 5
print(f"a >> 2 = {result}  (二进制: {bin(result)})")

result = a >> 3  # 右移3位: 10 = 2
print(f"a >> 3 = {result}  (二进制: {bin(result)})")

print()
print("规则：向右移动n位，左边补0（正数）")
print("效果：相当于整除 2^n")
print("💡 20 >> 1 = 20 // 2 = 10")
print("💡 20 >> 2 = 20 // 4 = 5")

print()

# ==================== 8. 实战：判断奇偶数 ====================
print("=" * 50)
print("8. 实战：用位运算判断奇偶数")
print("=" * 50)

def is_odd_bitwise(n):
    """使用位运算判断奇偶数"""
    return n & 1 == 1

numbers = [10, 15, 7, 22, 33]
for num in numbers:
    print(f"{num} 是{'奇数' if is_odd_bitwise(num) else '偶数'}")

print()
print("💡 原理：奇数的二进制最后一位是1，偶数是0")
print("   用 n & 1 可以得到最后一位")

print()

# ==================== 9. 实战：交换两个数 ====================
print("=" * 50)
print("9. 实战：用异或交换两个数（无需中间变量）")
print("=" * 50)

a = 5
b = 10
print(f"交换前：a = {a}, b = {b}")

# 使用异或交换
a = a ^ b
b = a ^ b
a = a ^ b

print(f"交换后：a = {a}, b = {b}")

print()
print("💡 原理：异或的特性")
print("   1. n ^ n = 0")
print("   2. n ^ 0 = n")
print("   3. 异或满足交换律和结合律")

print()

# ==================== 10. 实战：权限管理 ====================
print("=" * 50)
print("10. 实战：权限管理系统")
print("=" * 50)

# 定义权限常量（使用2的幂次）
READ = 1    # 0001 = 读权限
WRITE = 2   # 0010 = 写权限
EXECUTE = 4 # 0100 = 执行权限
DELETE = 8  # 1000 = 删除权限

print("权限定义：")
print(f"READ    = {READ}    (二进制: {bin(READ)})")
print(f"WRITE   = {WRITE}   (二进制: {bin(WRITE)})")
print(f"EXECUTE = {EXECUTE} (二进制: {bin(EXECUTE)})")
print(f"DELETE  = {DELETE}  (二进制: {bin(DELETE)})")
print()

# 授予权限：使用按位或 |
user_permission = 0  # 初始无权限
print(f"初始权限：{user_permission} (二进制: {bin(user_permission)})")

# 授予读权限
user_permission = user_permission | READ
print(f"授予读权限：{user_permission} (二进制: {bin(user_permission)})")

# 授予写权限
user_permission = user_permission | WRITE
print(f"授予写权限：{user_permission} (二进制: {bin(user_permission)})")

# 同时授予多个权限
user_permission = user_permission | EXECUTE | DELETE
print(f"授予执行和删除权限：{user_permission} (二进制: {bin(user_permission)})")
print()

# 检查权限：使用按位与 &
print("检查权限：")
has_read = (user_permission & READ) == READ
has_write = (user_permission & WRITE) == WRITE
has_execute = (user_permission & EXECUTE) == EXECUTE
has_delete = (user_permission & DELETE) == DELETE

print(f"有读权限：{has_read}")
print(f"有写权限：{has_write}")
print(f"有执行权限：{has_execute}")
print(f"有删除权限：{has_delete}")
print()

# 撤销权限：使用按位与和取反 &~
print("撤销写权限：")
user_permission = user_permission & ~WRITE
print(f"当前权限：{user_permission} (二进制: {bin(user_permission)})")

has_write = (user_permission & WRITE) == WRITE
print(f"有写权限：{has_write}")

print()

# ==================== 11. 实战：快速计算 ====================
print("=" * 50)
print("11. 实战：用位运算进行快速计算")
print("=" * 50)

n = 15

# 快速乘以2的幂次
print(f"n = {n}")
print(f"n * 2   = n << 1 = {n << 1}")
print(f"n * 4   = n << 2 = {n << 2}")
print(f"n * 8   = n << 3 = {n << 3}")
print(f"n * 16  = n << 4 = {n << 4}")

print()

# 快速除以2的幂次
n = 100
print(f"n = {n}")
print(f"n / 2   = n >> 1 = {n >> 1}")
print(f"n / 4   = n >> 2 = {n >> 2}")
print(f"n / 8   = n >> 3 = {n >> 3}")
print(f"n / 16  = n >> 4 = {n >> 4}")

print()
print("💡 位运算比普通乘除法更快")

print()

# ==================== 12. 实战：颜色值处理 ====================
print("=" * 50)
print("12. 实战：RGB颜色值处理")
print("=" * 50)

# RGB颜色通常用一个整数表示：0xRRGGBB
color = 0xFF5733  # 红色=FF, 绿色=57, 蓝色=33

print(f"颜色值：0x{color:06X}")
print()

# 提取各个颜色分量
red = (color >> 16) & 0xFF   # 右移16位，取低8位
green = (color >> 8) & 0xFF  # 右移8位，取低8位
blue = color & 0xFF          # 直接取低8位

print(f"红色分量：{red}  (0x{red:02X})")
print(f"绿色分量：{green}  (0x{green:02X})")
print(f"蓝色分量：{blue}  (0x{blue:02X})")
print()

# 合成颜色值
new_red = 128
new_green = 200
new_blue = 50

new_color = (new_red << 16) | (new_green << 8) | new_blue
print(f"合成新颜色：R={new_red}, G={new_green}, B={new_blue}")
print(f"颜色值：0x{new_color:06X}")

print()

# ==================== 13. 实战：状态标志 ====================
print("=" * 50)
print("13. 实战：多状态标志管理")
print("=" * 50)

# 定义状态标志
ONLINE = 1      # 0001 在线
BUSY = 2        # 0010 忙碌
AWAY = 4        # 0100 离开
INVISIBLE = 8   # 1000 隐身

print("状态标志：")
print(f"ONLINE    = {ONLINE}    (在线)")
print(f"BUSY      = {BUSY}      (忙碌)")
print(f"AWAY      = {AWAY}      (离开)")
print(f"INVISIBLE = {INVISIBLE} (隐身)")
print()

# 用户状态
user_status = ONLINE | BUSY  # 在线且忙碌

print(f"用户状态：{user_status} (二进制: {bin(user_status)})")
print()

# 检查状态
print("状态检查：")
print(f"是否在线：{(user_status & ONLINE) != 0}")
print(f"是否忙碌：{(user_status & BUSY) != 0}")
print(f"是否离开：{(user_status & AWAY) != 0}")
print(f"是否隐身：{(user_status & INVISIBLE) != 0}")

print()

# 切换状态（异或）
print("切换忙碌状态：")
user_status = user_status ^ BUSY  # 切换忙碌状态
print(f"新状态：{user_status} (二进制: {bin(user_status)})")
print(f"是否忙碌：{(user_status & BUSY) != 0}")

print()

# ==================== 14. 实战：找出唯一的数 ====================
print("=" * 50)
print("14. 实战：找出数组中唯一的数")
print("=" * 50)

# 问题：数组中除了一个数外，其他数都出现了两次，找出这个唯一的数
numbers = [4, 1, 2, 1, 2, 5, 4]
print(f"数组：{numbers}")

# 使用异或的特性：n ^ n = 0, n ^ 0 = n
result = 0
for num in numbers:
    result ^= num

print(f"唯一的数是：{result}")
print()
print("💡 原理：相同的数异或为0，所有数异或后剩下的就是唯一的数")

print()

# ==================== 总结 ====================
print("=" * 50)
print("✨ 位运算符总结")
print("=" * 50)
print("""
1. & (按位与)：两位都是1才是1
2. | (按位或)：有一位是1就是1
3. ^ (按位异或)：两位不同为1，相同为0
4. ~ (按位取反)：0变1，1变0
5. << (左移)：向左移n位，相当于乘以2^n
6. >> (右移)：向右移n位，相当于除以2^n

💡 常见应用场景：
- 判断奇偶：n & 1
- 交换数值：a ^ b 技巧
- 权限管理：用不同的位表示不同权限
- 快速计算：乘除2的幂次
- 颜色处理：提取RGB分量
- 状态标志：用一个整数表示多个布尔状态

💡 优势：
- 运算速度快
- 节省内存
- 代码简洁

⚠️ 注意：
- 位运算主要用于整数
- 理解二进制是基础
- 使用场景相对专业
- 可读性可能不如普通运算
""")
print("=" * 50)

